package com.itany.task.task;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class ThreadExecutorConfig {


    /*
        jdk提供的线程池
            1.Executors.newSingleThreadExecutor();
                创建一个单例的线程池，可以按照任务（FIFO，LIFO）的顺序执行
            2.Executors.newFixedThreadPool();
                创建一个定长的线程池，可以控制最大并发数量，超出的线程会在等待队列中等待
            3.Executors.newCachedThreadPool();
                创建一个可以缓存的线程池，线程池的长度可以反复修改
            4.Executors.newScheduledThreadPool();
                创建一个可以定期或延迟执行的线程池
     */
    @Bean("myExecutor")
    public Executor executor(){
        ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();


        /*
            核心线程数
            可以理解为最小线程数
            一个任务交给线程池执行后
            线程池会寻找空闲的线程执行
            如果执行完毕则回收空闲线程

            CPU密集型：计算多          java CUP核心数+1
            IO密集型：IO操作多         java CUP核心数*2
         */
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors()+1);


        /*
            任务队列长度
            当核心线程数到最大值时
            新的任务会存到任务队列中
         */
        executor.setQueueCapacity(20);


        /*
            最大线程数
            当任务队列也满
            则线程池判断线程数量是否超过max数量
            如果没有超过
            则新建线程对象执行任务
         */
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors()+1+10);


        /*
            线程空闲时间
         */
        executor.setKeepAliveSeconds(60);


        /*
            拒绝策略
                1.ThreadPoolExecutor.AbortPolicy()
                    直接抛出异常，阻止系统运行（线程池默认拒绝策略）
                2.ThreadPoolExecutor.CallerRunsPolicy()
                    由调用线程处理
                3.ThreadPoolExecutor.DiscardPolicy()
                    丢弃无任何处理
                4.ThreadPoolExecutor.DiscardOldestPolicy()
                    丢弃最老的一个线程
                    提交当前任务给线程池
         */
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());


        executor.setThreadNamePrefix("thread-");

        executor.initialize();


        return executor;
    }


}
